package com.tina.controller;


import com.alibaba.fastjson.JSONObject;
import com.tina.entity.Flowers;
import com.tina.entity.PageEntity;
import com.tina.service.IFlowersService;
import com.tina.util.HtmlParseUtil;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 商品表 前端控制器
 * </p>
 *
 * @author Tina
 * @since 2020-10-26
 */
@RestController
@RequestMapping("/flowers/")
public class FlowersController {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private IFlowersService flowersService;

    private Logger logger = LoggerFactory.getLogger(FlowersController.class);


    @Autowired
    private HtmlParseUtil htmlParseUtil;


    /**
     * 从jd爬取数据批量插入数据库
     *
     * @param key
     * @return
     * @throws IOException
     */
    @GetMapping("parse/{key}")
    public boolean parse(@PathVariable String key) throws IOException {

        List<Flowers> foods = htmlParseUtil.parseJd(key);
        boolean saveBatch = flowersService.saveBatch(foods);

        return saveBatch;
    }


    /**
     * 查询数据
     *
     * @param flowers
     * @param page
     * @param limit
     * @return
     * @throws IOException
     */
    @GetMapping("list")
    public PageEntity list(Flowers flowers, @RequestParam("page") Integer page, @RequestParam("limit") Integer limit) throws IOException {
        ArrayList<Map<String, Object>> maps = esData(flowers, page, limit);
        if (maps.size() < 1) {
            bulkDta(new Flowers());
            ArrayList<Map<String, Object>> s = esData(flowers, page, limit);
            return new PageEntity((long) s.size(), s, null, null);
        }
        return new PageEntity((long) maps.size(), maps, null, null);
    }

    /**
     * 从ES中查询数据
     *
     * @param flowers
     * @param page
     * @param limit
     * @return
     * @throws IOException
     */
    private ArrayList<Map<String, Object>> esData(Flowers flowers, Integer page, Integer limit) throws IOException {
        SearchRequest request = new SearchRequest("tina_index");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 分页
        builder.from(page - 1);
        builder.size(limit);
        // 条件查询

        //builder.sort("addTime", SortOrder.DESC);
        request.source(builder);
        SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        logger.info("search->{}", search);
        // 接收结果
        ArrayList<Map<String, Object>> arrayList = new ArrayList<Map<String, Object>>();
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : search.getHits().getHits()) {
            arrayList.add(hit.getSourceAsMap());
        }
        return arrayList;
    }

    /**
     * 插入数据
     *
     * @param flowers
     * @return
     * @throws IOException
     */
    private Boolean bulkDta(Flowers flowers) throws IOException {
        logger.info("flowers->{}", flowers);
        BulkRequest bulkRequest = new BulkRequest();
        List<Flowers> foods = flowersService.selectFlowers(flowers);

        for (Flowers food : foods) {
            bulkRequest.add(
                    new IndexRequest("tina_index")
                            .id(String.valueOf(food.getId())).source(JSONObject.toJSONString(food), XContentType.JSON)
            );
        }
        // 成功 false 失败true
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        return bulk.hasFailures();
    }

    /**
     * 批量插入数据到搜索引擎中
     *
     * @param flowers
     * @return
     * @throws IOException
     */
    @GetMapping("bulk")
    public Boolean bulk(Flowers flowers) throws IOException {

        return bulkDta(flowers);
    }


    /**
     * 搜索引擎
     */
    @GetMapping("searchRed/{title}")
    public ArrayList<Map<String, Object>> searchRed(@PathVariable String title) throws IOException {

        // 条件搜索
        SearchRequest request = new SearchRequest("tina_index");
        SearchSourceBuilder builder = new SearchSourceBuilder();

        // 分页
        builder.from(0);
        builder.size(10);

        // 高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        // 关闭多个高亮
        highlightBuilder.requireFieldMatch(true);
        highlightBuilder.preTags("<span class='search'>");
        highlightBuilder.postTags("</span>");
        builder.highlighter(highlightBuilder);

        // 条件查询
        MatchQueryBuilder termQueryBuilder = QueryBuilders.matchQuery("title", title);
        builder.query(termQueryBuilder);

        // 发送请求
        request.source(builder);
        SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        // 接收结果
        ArrayList<Map<String, Object>> arrayList = new ArrayList<Map<String, Object>>();

        for (SearchHit hit : search.getHits().getHits()) {
            // arrayList.add(hit.getSourceAsMap());

            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField name = highlightFields.get("title");

            // 获取结果
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();

            // 解析高亮字段
            if (name != null) {
                Text[] fragments = name.fragments();
                String newName = "";
                for (Text fragment : fragments) {
                    newName += fragment;
                }
                sourceAsMap.put("title", newName);
            }
            // 高亮字段替换原来的内容
            arrayList.add(sourceAsMap);
        }
        for (Map<String, Object> map : arrayList) {
            System.out.println("map-> " + map);
        }
        return arrayList;
    }

}
